#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
// namespace xywl {
    template <class T>
    class myshared_ptr {
        public:
            myshared_ptr(T* p = nullptr)
            :_ptr(p), _count(new int(1)), _mutex(new mutex) {}
            ~myshared_ptr() {
                Release();
            }
            myshared_ptr(myshared_ptr<T>& other) 
            :_count(other._count), _ptr(other._ptr), _mutex(other._mutex){
                Add();
            }
            myshared_ptr<T>& operator=(myshared_ptr<T>& other) {
                if(_ptr != other._ptr) {
                    Release();
                    _count = other._count;
                    _ptr = other._ptr;
                    Add();
                }
                return *this;
            }
            int use_count() {
                return *_count;
            }
            T& operator*() {
                return *_ptr;
            }
            T* operator->() {
                return _ptr;
            }
        private: 
            void Release() {
                _mutex->lock();
                bool flag = false;
                if(--(*_count) == 0) {
                    delete _ptr;
                    delete _count;
                    flag = true;
                }
                _mutex->unlock();
                if(flag) {
                    delete _mutex;
                }
            }
            void Add() {
                _mutex->lock();
                (*_count)++;
                _mutex->unlock();
            }
        private:
            int* _count; // 引用计数
            T* _ptr;
            mutex* _mutex;
    };
// }

// using namespace xywl;


struct Test {
    Test(int n) : _n(n) {
        cout << "Test(" << _n << ") constructed" << endl;
    }
    ~Test() {
        cout << "Test(" << _n << ") destroyed" << endl;
    }
    void Print() const {
        cout << "Test value: " << _n << endl;
    }
private:
    int _n;
};

int main() {
    {
        myshared_ptr<Test> sp1(new Test(10));
        cout << "sp1.use_count() = " << sp1.use_count() << endl; // 1

        {
            myshared_ptr<Test> sp2(sp1);
            cout << "After sp2(sp1):" << endl;
            cout << "sp1.use_count() = " << sp1.use_count() << endl; // 2
            cout << "sp2.use_count() = " << sp2.use_count() << endl; // 2
            sp2->Print();
        } // sp2 离开作用域，引用计数 -1

        cout << "After sp2 destroyed:" << endl;
        cout << "sp1.use_count() = " << sp1.use_count() << endl; // 1
    } // sp1 离开作用域，引用计数变 0，Test对象销毁

    cout << "main end" << endl;
    return 0;
}